package com.sxbang.friday.service.impl;

import com.sxbang.friday.base.constant.ReportType;
import com.sxbang.friday.base.result.Results;
import com.sxbang.friday.dao.DictDao;
import com.sxbang.friday.dao.ReportCountDao;
import com.sxbang.friday.dao.ReportDao;
import com.sxbang.friday.dto.LoginUser;
import com.sxbang.friday.model.SysDict;
import com.sxbang.friday.model.SysReport;
import com.sxbang.friday.model.SysReportCount;
import com.sxbang.friday.model.vo.SysReportCountVO;
import com.sxbang.friday.service.ReportService;
import com.sxbang.friday.util.SecurityUtil;
import com.sxbang.friday.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

	@Resource
	private ReportDao reportDao;

	@Resource
    private DictDao dictDao;


    @Resource
    private ReportCountDao reportCountDao;


	@Override
	public Results<SysReport> getAllReports() {
		return Results.success(50, reportDao.getAllReports());
	}

	@Override
	public Results<SysReport> getAllReportsByPage(Integer offset, Integer limit) {
        return Results.success(reportDao.countAllReports().intValue(), reportDao.getAllReportsByPage(offset, limit));
	}

    @Override
    public Results<SysReport> save(SysReport reportDto) {
        LoginUser user = SecurityUtil.getLoginUser();
        reportDto.setUserId(user.getId());
        //1、先保存角色"
        reportDao.save(reportDto);
//        reportDao.saveReport(reportDto);
//        List<Long> permissionIds = reportDto.getPermissionIds();
        //移除0,permission id是从1开始
//        permissionIds.remove(0L);
        //2、保存角色对应的所有权限
//        if (!CollectionUtils.isEmpty(permissionIds)) {
//            reportPermissionDao.save(reportDto.getId(), permissionIds);
//        }
        return Results.success();
    }

    @Override
    public SysReport getReportById(Integer id) {
        return reportDao.getById(id);
    }

   /* @Override
    public Results update(SysReport reportDto) {
//        List<Long> permissionIds = reportDto.getPermissionIds();
//        permissionIds.remove(0L);
        //1、更新角色权限之前要删除该角色之前的所有权限
//        reportPermissionDao.deleteReportPermission(reportDto.getId());

        //2、判断该角色是否有赋予权限值，有就添加"
        *//*if (!CollectionUtils.isEmpty(permissionIds)) {
            reportPermissionDao.save(reportDto.getId(), permissionIds);
        }*//*

        //3、更新角色表
        int countData = reportDao.update(reportDto);

        if(countData > 0){
            return Results.success();
        }else{
            return Results.failure();
        }
    }*/

    @Override
    public Results delete(Integer id) {
//        List<SysReportUser> datas = reportUserDao.listAllSysReportUserByReportId(id);
//        if(datas.size() <= 0){
            reportDao.delete(id);
            return Results.success();
//        }
//        return Results.failure(ResponseCode.USERNAME_REPEAT.USER_ROLE_NO_CLEAR.getCode(),ResponseCode.USERNAME_REPEAT.USER_ROLE_NO_CLEAR.getMessage());
    }

    @Override
    public Results<SysReport> getReportByFuzzyReportNamePage(String reportName, Integer startPosition, Integer limit) {
        return Results.success(reportDao.countReportByFuzzyReportName(reportName).intValue(), reportDao.getReportByFuzzyReportNamePage(reportName,startPosition, limit));
    }

    @Override
    public Results getSelfReportsByPage(Integer offset, Integer limit) {
        LoginUser user = SecurityUtil.getLoginUser();
        Long userId = user.getId();
        List<SysReport> data = reportDao.getReportsByIdAndPage(userId, offset, limit);
        int count = reportDao.countByUserId(userId).intValue();
        return Results.success(count, data);
    }

    /*




    -- 体温数量统计
-- SELECT
-- -- *
-- COUNT(*) as `value`,t.temperature as `name`
-- from
-- sys_report t
--
-- WHERE
-- DATE_FORMAT(t.createTime, '%Y-%m-%d') >= '2021-01-09'
-- and DATE_FORMAT(t.createTime, '%Y-%m-%d') <= '2021-01-09'
-- GROUP BY t.temperature
-- ;
    */
    @Override
    public Results getChartTemperatureData(String startDate, String endDateStr) {

       /* List<Map<String, Object>> data = reportDao.getChartTemperatureData(startDateStr, endDateStr);
        Map<String, ArrayList> rs = new HashMap<>();
        rs.put("value", new ArrayList<>());
        rs.put("name", new ArrayList<>());
        for (Map map: data) {
            rs.get("value").add(map.get("value"));
            rs.get("name").add(map.get("name"));
        }*/
        List<SysReportCount> data = reportCountDao.query(ReportType.temperature.name(), startDate, startDate);
        List<SysReportCountVO> rs = new ArrayList<>();
        transData(data, rs, ReportType.temperature.name());
        return Results.success(rs);
    }


    /*

-- -- 旅行数量统计
-- SELECT
-- -- *
-- COUNT(*) as `value`,t.travel as `name`
-- from
-- sys_report t
--
-- WHERE
-- DATE_FORMAT(t.createTime, '%Y-%m-%d') >= '2021-01-09'
-- and DATE_FORMAT(t.createTime, '%Y-%m-%d') <= '2021-01-09'
-- GROUP BY t.travel
-- ;
    */

    @Override
    public Results getChartTravelData(String startDate, String endDate) {
        /*List<Map<String, Object>> data = reportDao.getChartTravelData(startDate, endDate);
        Map<String, ArrayList> rs = new HashMap<>();
        rs.put("value", new ArrayList<>());
        rs.put("name", new ArrayList<>());
        for (Map map: data) {
            rs.get("value").add(map.get("value"));
            rs.get("name").add(map.get("name"));
        }*/
        List<SysReportCount> data = reportCountDao.query(ReportType.travel.name(), startDate, endDate);
        List<SysReportCountVO> rs = new ArrayList<>();
        transData(data, rs, ReportType.travel.name());
        return Results.success(rs);
    }

    /*

-- -- 症状数量统计
-- SELECT
-- SUM(FIND_IN_SET('travel', t.physical_condition) >0) as travel
-- ,SUM(FIND_IN_SET('normal', t.physical_condition) >0) as normal
-- ,SUM(FIND_IN_SET('contact', t.physical_condition) >0) as contact
-- ,SUM(FIND_IN_SET('rheum', t.physical_condition) >0) as rheum
-- ,SUM(FIND_IN_SET('polypnea', t.physical_condition) >0) as polypnea
-- ,SUM(FIND_IN_SET('vomiting', t.physical_condition) >0) as vomiting
-- ,SUM(FIND_IN_SET('flustered', t.physical_condition) >0) as flustered
-- ,SUM(FIND_IN_SET('conjunctivitis', t.physical_condition) >0) as conjunctivitis
--
-- FROM
-- sys_report t
-- where
-- DATE_FORMAT(t.createTime, '%Y-%m-%d') >= '2021-01-09'
-- and DATE_FORMAT(t.createTime, '%Y-%m-%d') <= '2021-01-09'
-- ;
    */
    @Override
    public Results getChartPhysicalConditionData(String startDate, String endDate) {
//       Map<String, Object> data = reportDao.getChartPhysicalConditionData(startDate, endDate);
        List<SysReportCount> data = reportCountDao.query(ReportType.physical_condition.name(), startDate, endDate);
        List<SysReportCountVO> rs = new ArrayList<>();
        transData(data, rs, ReportType.physical_condition.name());
        return Results.success(rs);
    }

    /*


-- 填报数量统计
SELECT
-- *
count(*) as `value` , DATE_FORMAT(t.createTime, '%Y-%m-%d')  as `name`
FROM
sys_report t
where
DATE_FORMAT(t.createTime, '%Y-%m-%d') >= '2021-01-02'
and DATE_FORMAT(t.createTime, '%Y-%m-%d') <= '2021-01-12'
GROUP BY DATE_FORMAT(t.createTime, '%Y-%m-%d')

;
      */
/*    @Override
    public Results getChartCountData(String startDate, String endDate) {
//        List<Map<String, Object>> data = reportDao.getChartCountData(startDate, endDate);
        String type = "count";
        List<SysReportCount> data = reportCountDao.query(type, startDate,endDate);
        List<SysReportCountVO> rs = new ArrayList<>();
        transData(data, rs, null);
        return Results.success(rs);
    }*/

    @Override
    public void countReportData(Date now) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String startDate, endDate;
        startDate = endDate = sdf.format(now);
        List<Map<String, Object>> temperatureData = reportDao.getChartTemperatureData(startDate, endDate);
        List<Map<String, Object>> travelData = reportDao.getChartTravelData(startDate, endDate);
//        List<Map<String, Object>> countData = reportDao.getChartCountData(startDate, endDate);
        Map<String, Object> physicalConditionData = reportDao.getChartPhysicalConditionData(startDate, endDate);

        List<SysReportCount> list = new ArrayList();

        setData(temperatureData, list, ReportType.temperature.name());
        setData(travelData, list, ReportType.travel.name());
//        setData(countData, list, "count");
        if (physicalConditionData != null) {
            for (String key : physicalConditionData.keySet()) {
                SysReportCount count = new SysReportCount();
                count.setName(key);
                count.setValue(physicalConditionData.get(key).toString());
                count.setType(ReportType.physical_condition.name());
                count.setCreateTime(new Date());
                list.add(count);
            }
        }
        System.out.println(" --- data ----" + list.size());
        for (SysReportCount item : list) {
            item.setReportDate(startDate);
            reportCountDao.delete(item);
            reportCountDao.save(item);
        }
    }

    @Override
    public Results refresh() {
        this.countReportData(new Date());
        return Results.success();
    }

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    @Override
    public Results getChartTemperatureLine(Date startDate, Date endDate, int past) {
        String startDateStr = sdf.format(startDate);
        String endDateStr = sdf.format(endDate);
        List<SysReportCount> data = reportCountDao.query(ReportType.temperature.name() ,startDateStr, endDateStr);
        List<SysReportCount> normalData = data.stream().filter(item->"NORMAL".equals(item.getName())).collect(Collectors.toList());;
        List<SysReportCount> lowData = data.stream().filter(item->"LOW".equals(item.getName())).collect(Collectors.toList());;
        List<SysReportCount> middleData = data.stream().filter(item->"MIDDLE".equals(item.getName())).collect(Collectors.toList());;
        List<SysReportCount> highData = data.stream().filter(item->"HIGH".equals(item.getName())).collect(Collectors.toList());;

        normalData = setDefaultLineData(normalData, endDate, past);
        lowData = setDefaultLineData(lowData, endDate, past);
        middleData = setDefaultLineData(middleData, endDate, past);
        highData = setDefaultLineData(highData, endDate, past);

        Map<String, List> rs = new HashMap<>();
        rs.put("NORMAL", normalData);
        rs.put("LOW", lowData);
        rs.put("MIDDLE", middleData);
        rs.put("HIGH", highData);
        return Results.success(rs);
    }

    private final int temperatureThresholdValue = 10;
    @Override
    public long countTemperatureLineData() {
        String startDateStr = sdf.format(new Date());
        String secondDate = sdf.format(getDay(1, new Date()));
        String temp = StrUtil.covertToQueryIn("HIGH", "MIDDLE");
        long flag = reportCountDao.sumValueByType("temperature", startDateStr, temp);
        long secondFlag = reportCountDao.sumValueByType("temperature", secondDate, temp);
        if (flag == 0) {
            return 0;
        }
        if (flag - secondFlag >= temperatureThresholdValue) {
            return flag;
        }
        return 0;
    }

    @Override
    public long countTemperatureData() {
        String startDateStr = sdf.format(new Date());
        return reportCountDao.sumValueByType("temperature", startDateStr, StrUtil.covertToQueryIn("HIGH", "MIDDLE"));
    }

    @Override
    public long countTravelData() {
        String startDateStr = sdf.format(new Date());
        return reportCountDao.sumValueByType("travel", startDateStr, StrUtil.covertToQueryIn("3", "2"));
    }

    @Override
    public long countPhysicalConditionData() {
        String startDateStr = sdf.format(new Date());
        return reportCountDao.sumValueByType("physical_condition", startDateStr, StrUtil.covertToQueryIn("contact", "rheum"));
    }


    private List<SysReportCount> setDefaultLineData(List<SysReportCount> list, Date startDate, int past){
        Map<String, SysReportCount> data = list.stream().collect(Collectors.toMap(SysReportCount::getReportDate,item->item));
        List<SysReportCount> rs = new ArrayList<>();
        for (int i = past - 1; i >= 0; i--) {
            Date firstDate = getDay(i, startDate);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String firstDateStr = sdf.format(firstDate);
            if (data.containsKey(firstDateStr)) {
                rs.add(data.get(firstDateStr));
            } else {
                SysReportCount sysReportCount = new SysReportCount();
                sysReportCount.setReportDate(firstDateStr);
                sysReportCount.setValue("0");
                rs.add(sysReportCount);
            }
        }
        return rs;
    }

    private Date getDay(int past, Date startPoint) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startPoint);
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - past);
        return calendar.getTime();
    }

    private void setData(List<Map<String, Object>> data, List list, String type){
        String nameStr = "name";
        String valueStr = "value";
        for (Map<String, Object> map : data) {
            SysReportCount count = new SysReportCount();
            count.setName(map.get(nameStr).toString());
            count.setValue(map.get(valueStr).toString());
            count.setType(type);
            list.add(count);
        }
    }

    private void transData(List<SysReportCount> data, List<SysReportCountVO> target, String type){
        Map<String, String> map = new HashMap<>();
        if (null != type) {
           List<SysDict> list = dictDao.getDictInType(type);
            map = list.stream().collect(Collectors.toMap(SysDict::getDictKey, SysDict::getDictValue));
        }
        for (SysReportCount item : data ) {
            SysReportCountVO vo = new SysReportCountVO();
            BeanUtils.copyProperties(item, vo);
            if (null != type && map.containsKey(item.getName())) {
                vo.setLabel(map.get(item.getName()));
            }
            target.add(vo);
        }
    }

}
